package com.imflea.zero.utils;

import com.alibaba.fastjson.JSONObject;
import com.imflea.zero.util.base.CommonUtils;
import com.imflea.zero.util.ZeroJsonUtils;
import com.imflea.zero.constant.WxPayConstant;
import com.imflea.zero.exception.BizException;
import com.imflea.zero.model.entity.wx.config.FarmWXPayConfig;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author 祥保玉
 * @PackageName: com.imflea.zero.utils
 * @ClassName: WxPayUtils
 * @Description
 * @date 2021-09-26  14:18:18
 */
public class WxPayUtils {

    private static Logger logger = LoggerFactory.getLogger(WxPayUtils.class);

    /**
     * @param config          商户支付配置信息
     * @param productId       商品ID或商户订单id
     * @param orderNumber     订单编号
     * @param orderMoneyTotal 订单总价
     * @param goodsName       商品名称
     * @param openId          用户openId
     * @param tradeType       支付方式：小程序，扫码等
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author 祥保玉
     * @description
     * @date 2021/9/26  21:10
     */


    public static Map<String, String> unifiedorder(FarmWXPayConfig config, String productId, String paySn, BigDecimal orderMoneyTotal, String goodsName, String openId, String tradeType) throws Exception {
        //存放请求参数的集合
//        Map<String, String> packageParams = new HashMap<>();
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", config.getAppID());
        //商户号
        packageParams.put("mch_id", config.getMchID());
        //随机字符串（保证签名不重复）
        packageParams.put("nonce_str", WXPayUtil.generateNonceStr());
        //商品名称:或者添加详细的商户信息
        packageParams.put("body", goodsName);
        //订单号
        packageParams.put("out_trade_no", paySn);
        //订单总金额【单位：分】所以需要乘以100
        packageParams.put("total_fee", orderMoneyTotal.multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).toString());
//        packageParams.put("total_fee", "1");
        //终端ip
        packageParams.put("spbill_create_ip",CommonUtils.getHostIp());
        //订单到期时间
        //packageParams.put("time_expire","yyyyMMddHHmmss");
        //异步通知地址
        packageParams.put("notify_url", config.getNotifyUrl());
//        packageParams.put("notify_url", WxPayConstant.WX_NOTIFY_URL);
        packageParams.put("trade_type", tradeType);//小程序支付
        packageParams.put("sign", WXPayUtil.generateSignature(packageParams, config.getKey()));

        packageParams.put("product_id", productId);

        packageParams.put("openid", openId);
        WXPay wxpay = new WXPay(config);
        //发送统一下单请求
        Map<String, String> responseMap = wxpay.unifiedOrder(packageParams);
        logger.error(ZeroJsonUtils.mapToJson(responseMap));
        //验证返回结果 如果 支付类型是扫码：NATIVE 有值
        if (responseMap != null && !responseMap.isEmpty()) {
            //二维码链接
            String returnCode = responseMap.get("return_code");
            if (!CommonUtils.isNull(returnCode) && returnCode.equals(WxPayConstant.SUCCESS)) {
                return responseMap;
            } else {
                throw new BizException(responseMap.get("return_msg"));
            }

        }
        throw new BizException(WxPayConstant.PAY_STATUS_MSG_FAIL);
    }

    /**
     * @param config
     * @param orderNumber 订单编号
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author 祥保玉
     * @description
     * @date 2021/9/26  21:11
     */


    public static Map<String, String> payFinish(WXPayConfig config, String orderNumber) throws Exception {
        Map<String, String> packageParams = new HashMap<>();
        //商户订单号
        packageParams.put("out_trade_no", orderNumber);
        WXPay wxpay = new WXPay(config);
        Map<String, String> responseMap = wxpay.orderQuery(packageParams);

        if (responseMap != null
                //请求正常
                && WxPayConstant.SUCCESS.equals(responseMap.get("return_code"))
                //业务正常
                && WxPayConstant.SUCCESS.equals(responseMap.get("result_code"))
                //状态是成功
                && WxPayConstant.SUCCESS.equals(responseMap.get("trade_state"))
        ) {
            return responseMap;

        } else {
            throw new BizException("请先完成支付");
        }
    }

    /**
     * @param config
     * @param
     * @param rebackOrderNumber 退款订单编号
     * @param refundAmount      退款金额
     * @param totalFee          订单原总价
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author 祥保玉
     * @description 申请退款
     * @date 2021/9/26  21:11
     */


    public static Map<String, String> doRefund(WXPayConfig config, String paySn, String rebackOrderNumber, BigDecimal refundAmount, BigDecimal totalFee) throws Exception {
        Map<String, String> packageParams = new HashMap<>();
        //商户订单号
        packageParams.put("out_trade_no", paySn);
        //商户退款单号
        packageParams.put("out_refund_no", rebackOrderNumber);
        //订单金额（单位：分）
        packageParams.put("total_fee", totalFee.multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).toString());
//        packageParams.put("total_fee", "1");
        //退款金额（单位：分）
        packageParams.put("refund_fee", refundAmount.multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).toString());
//        packageParams.put("refund_fee", "1");
        WXPay wxpay = new WXPay(config);
        Map<String, String> returnParams = wxpay.refund(packageParams);
        if (WxPayConstant.SUCCESS.equals(returnParams.get("result_code"))) {
            return returnParams;
        } else {
            throw new BizException(returnParams.get("err_code_des"));
        }
    }

    /**
     * @param config      订单支付/退款凭证
     * @param orderNumber 订单编号
     * @return java.lang.Boolean
     * @author 祥保玉
     * @description 关闭订单
     * @date 2021/9/26  21:12
     */


    public static Boolean closeOrders(WXPayConfig config, String orderNumber) throws Exception {
        //存放请求参数的集合
        Map<String, String> packageParams = new HashMap<>();
        //商户订单号
        packageParams.put("out_trade_no", orderNumber);
        WXPay wxpay = new WXPay(config);
        Map<String, String> responseMap = wxpay.closeOrder(packageParams);
        if (responseMap != null && WxPayConstant.SUCCESS.equals(responseMap.get("return_code")) && WxPayConstant.SUCCESS.equals(responseMap.get("result_code"))) {
            return true;
        } else {
            throw new BizException("关闭订单失败");
        }
    }

    /**
     * @param
     * @param apiKey
     * @return java.lang.String
     * @author 祥保玉
     * @description 微信回到
     * @date 2021/9/26  15:19
     */


    public static String wxCallback(Map<String, String> params, String apiKey) throws Exception {


        Map<String, String> returnData = new HashMap<>();
        logger.error(ZeroJsonUtils.mapToJson(params));
        if (!WXPayUtil.isSignatureValid(params, apiKey, WXPayConstants.SignType.HMACSHA256)) {
            // 支付失败
            logger.error("支付回调校验失败==>" + JSONObject.toJSONString(params));
            returnData.put("return_code", "FAIL");
            returnData.put("return_msg", "return_code不正确");
            logger.error("返回参数：" + WXPayUtil.mapToXml(returnData));
            return WXPayUtil.mapToXml(returnData);
        }
        logger.error("===============付款成功==============");
        String out_trade_no = params.get("out_trade_no").toString();//查询订单号
        String amountpaid = params.get("total_fee").toString();// 实际支付的订单金额:单位 分
        returnData.put("return_code", WxPayConstant.SUCCESS);
        returnData.put("return_msg", "OK");
        logger.error("返回参数：" + WXPayUtil.mapToXml(returnData));
        return WXPayUtil.mapToXml(returnData);
    }

    public static Map<String, String> wxCallbackToMap(Map<String, String> params, String apiKey) throws Exception {


        Map<String, String> returnData = new HashMap<>();
        logger.error(ZeroJsonUtils.mapToJson(params));
        if (!WXPayUtil.isSignatureValid(params, apiKey, WXPayConstants.SignType.HMACSHA256)) {
            // 支付失败
            logger.error("支付回调校验失败==>" + JSONObject.toJSONString(params));
            returnData.put("return_code", "FAIL");
            returnData.put("return_msg", "return_code不正确");
            logger.error("返回参数：" + WXPayUtil.mapToXml(returnData));
            return returnData;
        }
        logger.error("===============付款成功==============");
        String out_trade_no = params.get("out_trade_no").toString();//查询订单号
        String amountpaid = params.get("total_fee").toString();// 实际支付的订单金额:单位 分
        returnData.put("return_code", WxPayConstant.SUCCESS);
        returnData.put("return_msg", "OK");
        logger.error("返回参数：" + WXPayUtil.mapToXml(returnData));
        return returnData;
    }


}
